package com.lixw.jdbc.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: DaoUtils
 * @Description:
 * @Author: xuweiLi
 * @Create: 2025/6/10 08:55
 **/
public class DaoUtils {
    public static int update(String sql,Object... args){
        try {
            PreparedStatement preparedStatement = DbUtils.preparedStatement(sql);

            //设置？的值
            if(args !=null && args.length>0){
                for (int i = 0; i < args.length; i++) {
                    preparedStatement.setObject(i+1, args[i]);
                }
            }

            int len = preparedStatement.executeUpdate();
            preparedStatement.close();
            return len;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> List<T> query(Class<T> clazz, String sql, Object... args){
        try {
            PreparedStatement preparedStatement = DbUtils.preparedStatement(sql);

            //设置？的值
            if(args !=null && args.length>0){
                for (int i = 0; i < args.length; i++) {
                    preparedStatement.setObject(i+1, args[i]);
                }
            }

            ResultSet resultSet = preparedStatement.executeQuery();
            List<T> list = new ArrayList<>();

            ResultSetMetaData metaData = resultSet.getMetaData();
            //metaData是元数据，包含结果集有几列，以及每一列的标题是什么

            while (resultSet.next()){//while循环循环一次，遍历一行，一行就是一个Java的对象

                //通过clazz创建对应类型的对象
                //构造器可以是非公共的，但是必须有无参构造（约定）
                Constructor constructor = clazz.getDeclaredConstructor();
                constructor.setAccessible(true);
                T obj = (T) constructor.newInstance();

                for(int i = 1; i<=metaData.getColumnCount(); i++){
                    //属性值
//                    String columnName = metaData.getColumnName(i);//获取表中的字段的原名称
                    String columnName = metaData.getColumnLabel(i);//如果字段有别名就用别名，没有别名就用原名
                    Field field = clazz.getDeclaredField(columnName);
                    field.setAccessible(true);
                    field.set(obj, resultSet.getObject(i));
                }

                list.add(obj);
            }

            resultSet.close();
            preparedStatement.close();

            return list;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T queryObject(Class<T> clazz, String sql,Object... args){
        List<T> list = query(clazz, sql, args);
        if(list.size()>0){
            return list.get(0);
        }
        return null;
    }

    public static Object queryValue(String sql,Object... args){
        try {
            PreparedStatement preparedStatement = DbUtils.preparedStatement(sql);

            //设置？的值
            if (args != null && args.length > 0) {
                for (int i = 0; i < args.length; i++) {
                    preparedStatement.setObject(i + 1, args[i]);
                }
            }

            ResultSet resultSet = preparedStatement.executeQuery();

            if(resultSet.next()){
                return resultSet.getObject(1);
            }
        }catch(Exception e){
            throw new RuntimeException(e);
        }
        return null;
    }

    public static Map<Object,Object> queryMap(String sql, Object... args){
        Map<Object,Object> map = new HashMap<>();
        try {
            PreparedStatement preparedStatement = DbUtils.preparedStatement(sql);

            //设置？的值
            if (args != null && args.length > 0) {
                for (int i = 0; i < args.length; i++) {
                    preparedStatement.setObject(i + 1, args[i]);
                }
            }

            ResultSet resultSet = preparedStatement.executeQuery();

            while(resultSet.next()){//while循环循环一次，代表一行
                Object key = resultSet.getObject(1);
                Object value = resultSet.getObject(2);
                map.put(key,value);
            }

        }catch(Exception e){
            throw new RuntimeException(e);
        }
        return map;
    }
}